#include "Session.h"


void Session::HandleRead(const boost::system::error_code &error,
	size_t bytesTransfered)
{
	if (!error)
	{
		//create a message object
		Message	receivedMessage(reinterpret_cast<unsigned char*>(data_));

		//The message must be always in this format:
		// SOURCE DESTINATION other message elements
		// ** The message elements must be separated by a simple space
		string strMessage = receivedMessage.GetMessageStr();
		cout << "Received Message: " << strMessage << endl;
		vector<string> subStrings;
		boost::split(subStrings, strMessage, boost::is_any_of(" "));

		//if the message is a request to verify if there is any message for the sender
		if (receivedMessage.GetMessageHeader().GetMessageType() == MessageType::ANY_MESSAGE_FOR_ME)
		{
			//search the message table to find any messages destinated to the sender
			string source = subStrings[0];
			int numMessages = messages->size();
			bool foundMessage = false;

			for (int i = 0; i< numMessages; i++)
			{
				pair<string, Message> p = messages->at(i);

				//if found a message destinated to the sender
				if (boost::iequals(p.first, source))
				{
					//send 
					string msgBuffer = p.second.GetMessageBuffer();

					//erase from the messages table
					messages->erase(messages->begin() + i);

					boost::asio::async_write(socket_,
						boost::asio::buffer(msgBuffer.c_str(), msgBuffer.length()),
						boost::bind(&Session::HandleWrite, this,
						boost::asio::placeholders::error));
					foundMessage = true;
					break;					
				}
			}

			if (!foundMessage)
			{
				MessageHeader noMsgHeader(5, MessageType::NO_MESSAGES_FOR_YOU);
				Message noMsg(noMsgHeader, "");
				string noMsgBuffer = noMsg.GetMessageBuffer();
				boost::asio::async_write(socket_,
					boost::asio::buffer(noMsgBuffer.c_str(), noMsgBuffer.length()),
					boost::bind(&Session::HandleWrite, this,
					boost::asio::placeholders::error));
			}

		}
		else
		{

			//parse the destination
			string destination = subStrings[1];

			//insert the message into the messages table
			this->messages->push_back(make_pair(destination, receivedMessage));

			this->socket_.async_read_some(boost::asio::buffer(data_, MAX_LENGTH),
				boost::bind(&Session::HandleRead, this,
				boost::asio::placeholders::error,
				boost::asio::placeholders::bytes_transferred));

		}

		
	}
	else
	{
		delete this;
	}
}
void Session::HandleWrite(const boost::system::error_code &error)
{
	if (!error)
	{
		this->socket_.async_read_some(boost::asio::buffer(data_, MAX_LENGTH),
			boost::bind(&Session::HandleRead, this,
			boost::asio::placeholders::error,
			boost::asio::placeholders::bytes_transferred));
	}
	else
	{
		delete this;
	}
}


Session::Session(boost::asio::io_service &ioService, vector<pair<string, Message>> *messages) : socket_(ioService)
{
	this->messages = messages;
}

tcp::socket& Session::Socket()
{
	return socket_;
}

void Session::Start()
{
	this->socket_.async_read_some(boost::asio::buffer(data_, MAX_LENGTH),
		boost::bind(&Session::HandleRead, this,
		boost::asio::placeholders::error,
		boost::asio::placeholders::bytes_transferred));
}


